using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using Infrastructure.Domain;

namespace System
{
    public static class StringExtensions
    {
        public static DateTime EmptyDate = new DateTime(1899, 12, 31);

        [DebuggerStepThrough]
        public static string ToProperCase(this string o)
        {

            string mText = o.ToSafeString();
            string rText = "";
            try
            {
                CultureInfo cultureInfo =
                    Thread.CurrentThread.CurrentCulture;
                TextInfo TextInfo = cultureInfo.TextInfo;
                rText = TextInfo.ToTitleCase(mText);
            }
            catch
            {
                rText = mText;
            }
            return rText;
        }

        [DebuggerStepThrough]
        public static bool IsEmptyDate(this DateTime? o)
        {
            if (!o.HasValue)
                return true;
            else
                return IsEmptyDate(o.Value);
        }

        [DebuggerStepThrough]
        public static bool IsEmptyDate(this DateTime o)
        {
            if (o == DateTime.MinValue || o == EmptyDate)
                return true;
            else
                return false;
        }

        [DebuggerStepThrough]
        public static IDisposable AsDisposable(this object o)
        {


            if (typeof(IDisposable).IsAssignableFrom(o.GetType()))
                return (IDisposable)o;
            else
                throw new InvalidCastException("Object is not IDisposable");
        }

        [DebuggerStepThrough]
        public static List<TSource> ToSafeList<TSource>(this IEnumerable<TSource> source)
        {
            if (source == null)
                return new List<TSource>();
            else
                return source.ToList();
        }
        
        [DebuggerStepThrough]
        public static string ToFriendlyString(this object o)
        {
            string val = ToSafeString(o);

            StringBuilder ret = new StringBuilder();
            char[] ary = val.ToCharArray();
            bool lastWasCap = false;
            foreach (char c in ary)
            {

                string s = c.ToString();
                int n = c;
                if (n == 32 | n == 95)
                {
                    ret.Append(" ");
                    lastWasCap = false;
                }
                else if (n >= 65 & n <= 90)
                {
                    //Capital letters
                    if (!lastWasCap)
                    {
                        ret.Append(" ");
                        lastWasCap = true;
                    }
                    ret.Append(s);
                }
                else
                {
                    lastWasCap = false;
                    ret.Append(s);
                }
            }
            return ret.ToString().Trim();

        }

        [DebuggerStepThrough]
        public static string ToQuarterString(this byte i)
        {
            switch (i)
            {
                case 1:
                    return "1st";

                case 2:
                    return "2nd";

                case 3:
                    return "3rd";

                case 4:
                    return "4th";

                default:
                    return string.Empty;

            }

        }

        [DebuggerStepThrough]
        public static string ToPercentString(this object o)
        {
            decimal ret = 0;
            if (o == null)
                return "0 %";
            else
            {
                decimal.TryParse(o.ToString(), out ret);
                ret = Math.Round(ret * 100, 0);
            }
            return String.Format("{0} %", ret);
        }

        [DebuggerStepThrough]
        public static string ToSafeString(this object o)
        {
            if (o == null)
                return string.Empty;

            return o.ToString().Trim();
        }

        [DebuggerStepThrough]
        public static int ToSafeInt(this object o)
        {
            int ret = 0;
            if (o == null)
                return ret;

            if (o.GetType().IsEnum)
                return (int)o;

            int.TryParse(o.ToSafeString(), out ret);
            return ret;
        }

        [DebuggerStepThrough]
        public static string ToDateString(this object o)
        {
            if (o == null)
                return string.Empty;

            DateTime dt = DateTime.MinValue;

            DateTime.TryParse(o.ToSafeString(), out dt);

            if (dt == DateTime.MinValue || dt.ToShortDateString().Trim() == "12/31/1899")
                return string.Empty;

            return dt.ToShortDateString();
        }

        [DebuggerStepThrough]
        public static DateTime ToSafeDate(this object o)
        {
            DateTime ret = new DateTime(1899, 12, 31);
            if (o != null)
            {
                DateTime.TryParse(o.ToSafeString(), out ret);
                if (ret == DateTime.MinValue)
                    ret = new DateTime(1899, 12, 31);
            }
            return ret;
        }

        [DebuggerStepThrough]
        public static DateTime ToSafeDateTime(this object o)
        {
            if (o == null)
                return EmptyDate;


            DateTime ret = EmptyDate;

            DateTime.TryParse(o.ToSafeString(), out ret);

            if (ret == DateTime.MinValue)
                return EmptyDate;

            return ret;
        }

        [DebuggerStepThrough]
        public static decimal ToSafeDecimal(this object o)
        {
            if (o == null)
                return 0;

            decimal ret = 0;

            decimal.TryParse(o.ToSafeString(), out ret);
            return ret;
        }

        [DebuggerStepThrough]
        public static bool ToSafeBool(this bool? o)
        {
            bool ret = false;
            if (!o.HasValue)
                return ret;
            ret = o.Value;
            return ret;
        }

        [DebuggerStepThrough]
        public static bool ToSafeBool(this object o)
        {
            bool ret = false;
            if (o == null)
                return ret;
            bool.TryParse(o.ToSafeString(), out ret);
            return ret;
        }

        [DebuggerStepThrough]
        public static double ToSafeDouble(this object o)
        {
            if (o == null)
                return 0;

            double ret = 0;

            double.TryParse(o.ToSafeString(), out ret);
            return ret;
        }

        [DebuggerStepThrough]
        public static short ToSafeShort(this object o)
        {
            if (o == null)
                return 0;

            short ret = 0;

            short.TryParse(o.ToSafeString(), out ret);
            return ret;
        }

        [DebuggerStepThrough]
        public static long ToSafeLong(this object o)
        {
            return o.ToSafelong();
        }

        [DebuggerStepThrough]
        public static long ToSafelong(this object o)
        {
            if (o == null)
                return 0;

            long ret = 0;

            if (o.GetType().IsEnum)
                return ((int)o);

            long.TryParse(o.ToSafeString(), out ret);
            return ret;
        }

        [DebuggerStepThrough]
        public static byte ToSafeByte(this object o)
        {
            byte ret = 0;
            if (o == null)
                return 0;


            if (o is bool && ((bool)o))
                return 1;

            if (o.GetType().IsEnum)
                return (byte)((int)o);
            byte.TryParse(o.ToSafeString(), out ret);
            return ret;
        }

        [DebuggerStepThrough]
        public static string ToYNString(this bool? o)
        {
            if (!o.HasValue)
                return "N";
            else if (o.Value)
                return "Y";
            else
                return "N";
        }

        [DebuggerStepThrough]
        public static char ToYNChar(this bool? o)
        {
            return ToYNString(o).ToCharArray()[0];
        }

        [DebuggerStepThrough]
        public static bool ToBoolean(this byte o)
        {
            if (o == 0)
                return true;
            else
                return false;
        }

        [DebuggerStepThrough]
        public static bool ToBoolean(this byte? o)
        {
            if (o.HasValue)
                return ToBoolean(o.Value);
            else
                return false;
        }

        [DebuggerStepThrough]
        public static bool ToBoolean(this int o)
        {
            if (o == 1)
                return true;
            else
                return false;
        }

        [DebuggerStepThrough]
        public static bool ToBoolean(this int? o)
        {
            if (o.HasValue)
                return ToBoolean(o.Value);
            else
                return false;
        }

        [DebuggerStepThrough]
        public static T FirstOrDefault<T>(this PagedList<T> list) where T : class
        {
            if (list == null || list.Count() == 0)
                return null;
            else
                return list.Data.First ();
        }
    }
}